package com.telemetria.controller;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;

import org.joda.time.DateTime;
import org.joda.time.Duration;

import com.telemetria.entity.Tempo;
import com.telemetria.entity.Volta;
import com.telemetria.entity.VoltaJoda;
import com.telemetria.util.TempoFormatter;
import com.telemetria.util.TempoUtil;

@ManagedBean(name = "telTempoController")
@SessionScoped
public class telTempoController implements Serializable{

	private static final long serialVersionUID = 1360289894862851250L;
	private static final String DEFAULT_BLANK_TIME ="--:--:---";
	
	protected Tempo tempo;
	protected Volta volta;
	protected long melhorVolta;
	protected long piorVolta;
	protected Volta difUltimaVolta;
	protected List<VoltaJoda> listaVoltas;
	protected DateTime tempoInicial;
	protected DateTime tempoFinal;
	protected DateTime tempoVolta;
	protected DateTime tempoTotal;
	protected DateTime mostraTempo;
	protected Integer nuVolta = 0;
	private boolean bloquearIniciaCont = false;
	private boolean bloquearEncerraCont = true;
	private boolean bloquearSensorVoltas = false;
	
	
	public void atualizaTempo(){
		setMostraTempo(DateTime.now());
	}
	
	public telTempoController(){
		listaVoltas = new ArrayList<VoltaJoda>();
		tempo = new Tempo();
		volta = new Volta();
		new DateTime();
	}
	
	public void iniciarCronometro(){		
		mostraTempo = tempoVolta = tempoInicial = DateTime.now();
		setBloquearIniciaCont(true);
		setBloquearEncerraCont(false);
	}
	
	public void encerraCronometro(){		
		tempoFinal =  DateTime.now();		
		long tempoTotalMilis = tempoFinal.getMillis() - tempoInicial.getMillis();		
		tempoTotal = new DateTime(tempoTotalMilis);
		setBloquearEncerraCont(true);
		setBloquearSensorVoltas(true);
	}
	
	public void completarVolta(){
		VoltaJoda volta = new VoltaJoda();
		
		//pega Duration da volta completada
		Duration durationAgora = new Duration(tempoVolta, DateTime.now());
		
		//zera tempo da volta
		tempoVolta = DateTime.now();
		
		Duration voltaCompletada = new Duration(durationAgora);
		
		volta.setId(nuVolta.longValue());
		volta.setNuVolta(nuVolta+1);
		volta.setUltimaVolta(voltaCompletada);
		volta.setUltimaVoltaStr(formataJodaTime(voltaCompletada));
		
		if(nuVolta > 0){
			
			calcularDifUltimaVolta(voltaCompletada, volta);
			
			calcularMediaVoltas(volta, listaVoltas);
			
			calculaMelhorVolta(volta, voltaCompletada);
			
			calcularPiorVolta(volta, voltaCompletada);
			
			if(nuVolta > 1){
				calcularDiffUltimaMedia(volta, listaVoltas);
			}else{
				volta.setDifUltimaMediaStr(DEFAULT_BLANK_TIME);
			}
		}else{
			volta.setMelhorVoltaStr(formataJodaTime(voltaCompletada));
			volta.setMelhorVolta(voltaCompletada);
			volta.setPiorVoltaStr(formataJodaTime(voltaCompletada));
			volta.setPiorVolta(voltaCompletada);
			
			melhorVolta = voltaCompletada.getMillis();
			piorVolta = voltaCompletada.getMillis();
			
			volta.setDifUltimaVoltaStr(DEFAULT_BLANK_TIME);
			volta.setMediaVoltasStr(DEFAULT_BLANK_TIME);
			volta.setDifUltimaMediaStr(DEFAULT_BLANK_TIME);
		}

		listaVoltas.add(volta);
		nuVolta++;
	}	

	private void calcularPiorVolta(VoltaJoda volta, Duration voltaCompletada) {
		
		if(voltaCompletada.getMillis() > piorVolta){
			piorVolta = voltaCompletada.getMillis();
			volta.setPiorVolta(new Duration(voltaCompletada));
			volta.setPiorVoltaStr(formataJodaTime(voltaCompletada));
		}else{
			volta.setPiorVolta(new Duration(piorVolta));
			volta.setPiorVoltaStr(formataJodaTime(new Duration(piorVolta)));
		}
	}

	private void calculaMelhorVolta(VoltaJoda volta, Duration voltaCompletada) {

		if(voltaCompletada.getMillis() < melhorVolta){
			melhorVolta = voltaCompletada.getMillis();
			volta.setMelhorVolta(new Duration(voltaCompletada));
			volta.setMelhorVoltaStr(formataJodaTime(voltaCompletada));
		}else{
			volta.setMelhorVolta(new Duration(melhorVolta));
			volta.setMelhorVoltaStr(formataJodaTime(new Duration(melhorVolta)));
		}
	}

	private void calcularMediaVoltas(VoltaJoda volta, List<VoltaJoda> listaVoltas) {
		
		long milis = 0;
		long result = 0;
		long totalVoltas = listaVoltas.size() + 1;//mais a volta atual;
		
		for (VoltaJoda voltaJoda : listaVoltas) {
			milis += voltaJoda.getUltimaVolta().getMillis();
		}
		milis += volta.getUltimaVolta().getMillis();//soma a volta atual
		
		result = milis / totalVoltas;
		
		volta.setMediaVoltas(new Duration(result));
		volta.setMediaVoltasStr(formataJodaTime(volta.getMediaVoltas()));
	}
	
	private void calcularDiffUltimaMedia(VoltaJoda volta, List<VoltaJoda> listaVoltas) {
		
		Duration duration1 = TempoUtil.difference(volta.getMediaVoltas(), listaVoltas.get(nuVolta-1).getMediaVoltas());
		
		if(duration1.getMillis() < 0 ){
			volta.setDifUltimaMediaStr("-".concat(formataJodaTime(duration1)));
		}else{
			volta.setDifUltimaMediaStr("+".concat(formataJodaTime(duration1)));
		}
		
		volta.setDifUltimaMedia(duration1);
	}

	private void calcularDifUltimaVolta(Duration tempoAgora, VoltaJoda volta) {
		
		Duration duration1 = TempoUtil.difference(tempoAgora, getUltimaVolta());
		
		if(duration1.getMillis() < 0 ){
			volta.setDifUltimaVoltaStr("-".concat(formataJodaTime(duration1)));
		}else{
			volta.setDifUltimaVoltaStr("+".concat(formataJodaTime(duration1)));
		}
		volta.setDifUltimaVolta(duration1);
	}
	
	private String formataJodaTime(Duration duration){
		return TempoFormatter.parseTempoJodaTime(duration);
	}
	
	private Duration getUltimaVolta(){		
		return this.listaVoltas.get(nuVolta-1).getUltimaVolta();
	}
	
	public Tempo getTempo() {
		return tempo;
	}
	
	public void setTempo(Tempo tempo) {
		this.tempo = tempo;
	}
	
	public Volta getVolta() {
		return volta;
	}
	
	public void setVolta(Volta volta) {
		this.volta = volta;
	}
	
	public List<VoltaJoda> getListaVoltas() {
		return listaVoltas;
	}
	
	public void setListaVoltas(List<VoltaJoda> listaVoltas) {
		this.listaVoltas = listaVoltas;
	}
	
	public static long getSerialversionuid() {
		return serialVersionUID;
	}


	public DateTime getTempoInicial() {
		return tempoInicial;
	}

	public void setTempoInicial(DateTime tempoInicial) {
		this.tempoInicial = tempoInicial;
	}

	public DateTime getTempoFinal() {
		return tempoFinal;
	}

	public void setTempoFinal(DateTime tempoFinal) {
		this.tempoFinal = tempoFinal;
	}

	public DateTime getTempoVolta() {
		return tempoVolta;
	}

	public void setTempoVolta(DateTime tempoVolta) {
		this.tempoVolta = tempoVolta;
	}

	public boolean isBloquearIniciaCont() {
		return bloquearIniciaCont;
	}

	public void setBloquearIniciaCont(boolean bloquearIniciaCont) {
		this.bloquearIniciaCont = bloquearIniciaCont;
	}

	public boolean isBloquearEncerraCont() {
		return bloquearEncerraCont;
	}

	public void setBloquearEncerraCont(boolean bloquearEncerraCont) {
		this.bloquearEncerraCont = bloquearEncerraCont;
	}

	public boolean isBloquearSensorVoltas() {
		return bloquearSensorVoltas;
	}

	public void setBloquearSensorVoltas(boolean bloquearSensorVoltas) {
		this.bloquearSensorVoltas = bloquearSensorVoltas;
	}

	public DateTime getMostraTempo() {
		return mostraTempo;
	}

	public void setMostraTempo(DateTime mostraTempo) {
		this.mostraTempo = mostraTempo;
	}

}
